package cn.rumoss.nettyinaction.echo;

import java.net.InetSocketAddress;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * Netty 实现的 echo 服务器都需要下面这些：
 * (1)一个服务器 handler：这个组件实现了服务器的业务逻辑，决定了连接创建后和接收到信息后该如何处理
 * (2)Bootstrapping： 这个是配置服务器的启动代码。最少需要设置服务器绑定的端口，用来监听连接请求
 * @author HeCG
 *
 */
public class EchoServer {

	private final int port;
	
	public EchoServer(int port) {
		this.port = port;
	}

	public void start() throws Exception {
		
		NioEventLoopGroup group = new NioEventLoopGroup();
		
		try {
			ServerBootstrap serverBootstrap = new ServerBootstrap();
			serverBootstrap.group(group)
				.channel(NioServerSocketChannel.class)// 指定使用 NIO 的传输 Channel
				.localAddress(new InetSocketAddress(port))
				.childHandler(new ChannelInitializer<SocketChannel>() {

						@Override
						protected void initChannel(SocketChannel ch) throws Exception {
							ch.pipeline().addLast(
									new EchoServerHandler());// 添加 EchoServerHandler 到 Channel 的 ChannelPipeline
						}

					});
			ChannelFuture future = serverBootstrap.bind().sync();// 绑定的服务器;sync(线程阻塞) 等待服务器关闭
			System.out.println(EchoServer.class.getName() + " 启动并且在监听着 " + future.channel().localAddress());
			future.channel().closeFuture().sync();// 关闭 channel 和 块，直到它被关闭
		} finally {
			group.shutdownGracefully().sync();// 关闭 EventLoopGroup，释放所有资源
		}
		
	}

	public static void main(String[] args) throws Exception {
		
		if(args.length!=1) {
			System.err.println("Usage: " + EchoServer.class.getName() + " <port>");
			return;
		}
		int port = Integer.parseInt(args[0]);
		new EchoServer(port).start();

	}

}
